package com.gp.common;

import java.util.HashMap;
import java.util.Map;

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.plugins.Page;
import com.gp.exception.CustomException;

/**
 * @author: 弓成龙
 * @date : 2017年12月18日
 * @email : gcx909109@sina.cn
 * @description: 解析page对象和基本类型
 */
public class PageHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    /**
     * 判断是否基本类型或者是page对象
     */
    Class<?> type = parameter.getParameterType();
    return Page.class == type; 
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
      /**
       * 装配Page对象
       */
      Page<?> page = new Page<Object>();
      String paramPage = webRequest.getParameter("page");
      return paramPage != null ? resolvePage(page, paramPage) : page;
    }
 
  /**
   * 处理Page类型的参数
   * 
   * @param page 需要进行装配的page对象
   * @param paramPage 从request 对象中获取的Json格式的Page参数字符串
   * @return 装配完成的page对象
   * @throws CustomException 返回参数不正确异常
   */
  @SuppressWarnings("unchecked")
  private Page<?> resolvePage(Page<?> page, String paramPage) throws CustomException {
    InnerPage innerPage = JSON.parseObject(paramPage, InnerPage.class);
    page.setTotal(innerPage.getTotal());
    page.setSize(innerPage.getSize());
    page.setCurrent(innerPage.getCurrent());
    page.setAsc(Boolean.parseBoolean(innerPage.getAsc()));
    page.setOrderByField(innerPage.getSortField());
    page.setOpenSort(Boolean.parseBoolean(innerPage.getOpenSort()));
    page.setSearchCount(Boolean.parseBoolean(innerPage.getSearchCount()));
    try {
      // 填充condition条件
      if (!innerPage.getCondition().trim().equals("")) {
        Map<String, Object> conditionMap = new HashMap<String, Object>();
        conditionMap
            .putAll((Map<? extends String, ? extends Object>) JSON.parse(innerPage.getCondition()));
        page.setCondition(conditionMap);
      }
    } catch (Exception e) {
      throw new CustomException("参数转型失败");
    }
    return page;
  }

  public final static class InnerPage {
    private int total = 0;
    private int size = 12;
    private int current = 1;
    private String asc = "true";
    private String sortField = "";
    private String openSort = "true";
    private String searchCount = "true";

    private String condition = "";

    private InnerPage() {}

    public int getSize() {
      return size;
    }

    public void setSize(int size) {
      this.size = size;
    }

    public int getCurrent() {
      return current;
    }

    public void setCurrent(int current) {
      this.current = current;
    }

    public String getSortField() {
      return sortField;
    }

    public void setSortField(String sortField) {
      this.sortField = sortField;
    }

    public String getCondition() {
      return condition;
    }

    public void setCondition(String condition) {
      this.condition = condition;
    }

    public String getOpenSort() {
      return openSort;
    }

    public void setOpenSort(String openSort) {
      this.openSort = openSort;
    }

    public String getAsc() {
      return asc;
    }

    public void setAsc(String asc) {
      this.asc = asc;
    }

    public int getTotal() {
      return total;
    }

    public void setTotal(int total) {
      this.total = total;
    }

    public String getSearchCount() {
      return searchCount;
    }

    public void setSearchCount(String searchCount) {
      this.searchCount = searchCount;
    }
  }
}

